Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
jest-mock-extended
Advanced tools
The jest-mock-extended package is a utility for creating strongly typed mocks in Jest. It allows you to create mocks, partial mocks, and deep mocks with type safety, ensuring that your tests are more reliable and maintainable.
Creating a simple mock
This feature allows you to create a simple mock of an interface or class. The mock object will have all the methods of the interface or class, and you can specify return values for these methods.
const { mock } = require('jest-mock-extended');
interface MyService {
doSomething(): string;
}
const myServiceMock = mock<MyService>();
myServiceMock.doSomething.mockReturnValue('mocked value');
console.log(myServiceMock.doSomething()); // Output: 'mocked value'
Creating a partial mock
This feature allows you to create a partial mock of an interface or class. You can specify implementations for some methods, while the rest will be undefined.
const { mockPartial } = require('jest-mock-extended');
interface MyService {
doSomething(): string;
doSomethingElse(): number;
}
const myServicePartialMock = mockPartial<MyService>({
doSomething: () => 'partial mock value'
});
console.log(myServicePartialMock.doSomething()); // Output: 'partial mock value'
console.log(myServicePartialMock.doSomethingElse()); // Output: undefined
Creating a deep mock
This feature allows you to create a deep mock of an interface or class. All nested properties and methods will be mocked, allowing you to specify return values for deeply nested methods.
const { mockDeep } = require('jest-mock-extended');
interface MyService {
nestedService: {
doSomething(): string;
};
}
const myServiceDeepMock = mockDeep<MyService>();
myServiceDeepMock.nestedService.doSomething.mockReturnValue('deep mock value');
console.log(myServiceDeepMock.nestedService.doSomething()); // Output: 'deep mock value'
ts-mockito is a mocking library for TypeScript that provides a fluent API for creating mocks, stubs, and spies. It is similar to jest-mock-extended in that it allows for type-safe mocking, but it uses a different API and is not specifically tied to Jest.
typemoq is another mocking library for TypeScript that provides a fluent API for creating mocks and spies. It is similar to jest-mock-extended in its focus on type safety, but it offers a different set of features and is not specifically designed for use with Jest.
Sinon is a popular JavaScript library for creating spies, stubs, and mocks. While it is not TypeScript-specific, it can be used with TypeScript and provides a wide range of features for mocking and spying. It is more general-purpose compared to jest-mock-extended, which is specifically designed for Jest and TypeScript.
Type safe mocking extensions for Jest 🃏
npm install jest-mock-extended --save-dev
or
yarn add jest-mock-extended --dev
import { mock } from 'jest-mock-extended';
interface PartyProvider {
getPartyType: () => string;
getSongs: (type: string) => string[]
start: (type: string) => void;
}
describe('Party Tests', () => {
test('Mock out an interface', () => {
const mock = mock<PartyProvider>();
mock.start('disco party');
expect(mock.start).toHaveBeenCalledWith('disco party');
});
test('mock out a return type', () => {
const mock = mock<PartyProvider>();
mock.getPartyType.mockReturnValue('west coast party');
expect(mock.getPartyType()).toBe('west coast party');
});
test('throwing an error if we forget to specify the return value')
const mock = mock<PartyProvider>(
{},
{
fallbackMockImplementation: () => {
throw new Error('not mocked');
},
}
);
expect(() => mock.getPartyType()).toThrowError('not mocked');
});
If you wish to assign a mock to a variable that requires a type in your test, then you should use the MockProxy<> type given that this will provide the apis for calledWith() and other built-in jest types for providing test functionality.
import { MockProxy, mock } from 'jest-mock-extended';
describe('test', () => {
let myMock: MockProxy<MyInterface>;
beforeEach(() => {
myMock = mock<MyInterface>();
})
test(() => {
myMock.calledWith(1).mockReturnValue(2);
...
})
});
jest-mock-extended
allows for invocation matching expectations. Types of arguments, even when using matchers are type checked.
const provider = mock<PartyProvider>();
provider.getSongs.calledWith('disco party').mockReturnValue(['Dance the night away', 'Stayin Alive']);
expect(provider.getSongs('disco party')).toEqual(['Dance the night away', 'Stayin Alive']);
// Matchers
provider.getSongs.calledWith(any()).mockReturnValue(['Saw her standing there']);
provider.getSongs.calledWith(anyString()).mockReturnValue(['Saw her standing there']);
You can also use mockFn()
to create a jest.fn()
with the calledWith extension:
type MyFn = (x: number, y: number) => Promise<string>;
const fn = mockFn<MyFn>();
fn.calledWith(1, 2).mockReturnValue('str');
jest-mock-extended
exposes a mockClear and mockReset for resetting or clearing mocks with the same
functionality as jest.fn()
.
import { mock, mockClear, mockReset } from 'jest-mock-extended';
describe('test', () => {
const mock: UserService = mock<UserService>();
beforeEach(() => {
mockReset(mock); // or mockClear(mock)
});
...
})
If your class has objects returns from methods that you would also like to mock, you can use mockDeep
in
replacement for mock.
import { mockDeep } from 'jest-mock-extended';
const mockObj: DeepMockProxy<Test1> = mockDeep<Test1>();
mockObj.deepProp.getNumber.calledWith(1).mockReturnValue(4);
expect(mockObj.deepProp.getNumber(1)).toBe(4);
if you also need support for properties on functions, you can pass in an option to enable this
import { mockDeep } from 'jest-mock-extended';
const mockObj: DeepMockProxy<Test1> = mockDeep<Test1>({ funcPropSupport: true });
mockObj.deepProp.calledWith(1).mockReturnValue(3)
mockObj.deepProp.getNumber.calledWith(1).mockReturnValue(4);
expect(mockObj.deepProp(1)).toBe(3);
expect(mockObj.deepProp.getNumber(1)).toBe(4);
Can can provide a fallback mock implementation used if you do not define a return value using calledWith
.
import { mockDeep } from 'jest-mock-extended';
const mockObj = mockDeep<Test1>({
fallbackMockImplementation: () => {
throw new Error('please add expected return value using calledWith');
},
});
expect(() => mockObj.getNumber()).toThrowError('not mocked');
Matcher | Description |
---|---|
any() | Matches any arg of any type. |
anyBoolean() | Matches any boolean (true or false) |
anyString() | Matches any string including empty string |
anyNumber() | Matches any number that is not NaN |
anyFunction() | Matches any function |
anyObject() | Matches any object (typeof m === 'object') and is not null |
anyArray() | Matches any array |
anyMap() | Matches any Map |
anySet() | Matches any Set |
isA(class) | e.g isA(DiscoPartyProvider) |
includes('value') | Checks if value is in the argument array |
containsKey('key') | Checks if the key exists in the object |
containsValue('value') | Checks if the value exists in an object |
has('value') | checks if the value exists in a Set |
notNull() | value !== null |
notUndefined() | value !== undefined |
notEmpty() | value !== undefined && value !== null && value !== '' |
captor() | Used to capture an arg - alternative to mock.calls[0][0] |
Custom matchers can be written using a MatcherCreator
import { MatcherCreator, Matcher } from 'jest-mock-extended';
// expectedValue is optional
export const myMatcher: MatcherCreator<MyType> = (expectedValue) => new Matcher((actualValue) => {
return (expectedValue === actualValue && actualValue.isSpecial);
});
By default, the expected value and actual value are the same type. In the case where you need to type the expected value differently than the actual value, you can use the optional 2 generic parameter:
import { MatcherCreator, Matcher } from 'jest-mock-extended';
// expectedValue is optional
export const myMatcher: MatcherCreator<string[], string> = (expectedValue) => new Matcher((actualValue) => {
return (actualValue.includes(expectedValue));
});
FAQs
Type safe mocking extensions for jest
The npm package jest-mock-extended receives a total of 374,716 weekly downloads. As such, jest-mock-extended popularity was classified as popular.
We found that jest-mock-extended demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.